package com.example.mymp3cut;

import android.annotation.SuppressLint;
import android.icu.text.RelativeDateTimeFormatter;
import android.media.AudioFormat;
import android.media.MediaCodec;
import android.media.MediaExtractor;
import android.media.MediaFormat;
import android.os.Environment;
import android.provider.MediaStore;
import android.util.Log;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class MusicProcess {
    private int selectTrack(MediaExtractor mediaExtractor) {
        int numTracks = mediaExtractor.getTrackCount();
        for (int i = 0; i < numTracks; i++){
            MediaFormat format = mediaExtractor.getTrackFormat(i);
            String mime = format.getString(MediaFormat.KEY_MIME);
            if (mime.startsWith("audio/")){
                return i;
            }
        }
        return -1;
    }

    @SuppressLint("WrongConstant")
    public void clip(String muiscPath, String outPath, int startTime, int endTime) throws IOException {
        if (startTime > endTime){
            Log.e("77777777777777777", "================ 66666666666666666 ================");

            return;
        }
        Log.e("77777777777777777", "================ 444444444444444 ================");

        MediaExtractor mediaExtractor = new MediaExtractor();
        mediaExtractor.setDataSource(muiscPath);
        int audioTrack = selectTrack(mediaExtractor);
        mediaExtractor.selectTrack(audioTrack);
        mediaExtractor.seekTo(startTime, MediaExtractor.SEEK_TO_CLOSEST_SYNC);
        MediaFormat sourceAudioFormat = mediaExtractor.getTrackFormat(audioTrack);
        int maxBufferSize = 1024 * 100;
        if (sourceAudioFormat.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)){
            maxBufferSize = sourceAudioFormat.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE);
        }

        ByteBuffer buffer = ByteBuffer.allocateDirect(maxBufferSize);
        MediaCodec mediaCodec = MediaCodec.createDecoderByType(sourceAudioFormat.getString(MediaFormat.KEY_MIME));
        mediaCodec.configure(sourceAudioFormat, null, null, 0);
        File pcmFile = new File(Environment.getExternalStorageDirectory(), "out.pcm");
        FileChannel writeChannel = new FileOutputStream(pcmFile).getChannel();
        mediaCodec.start();
        MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
        int outputBufferIndex = -1;
        while (true){
            int decodeInputIndex = mediaCodec.dequeueInputBuffer(1000000);
            if (decodeInputIndex >= -1){
                long sampleTimeUs = mediaExtractor.getSampleTime();
                if (sampleTimeUs == -1){
                    Log.e("7777777777777777777", "=============== clip: sampleTimeUs == -1 ===============" );
                    break;
                } else if(sampleTimeUs < startTime){
                    Log.e("7777777777777777777", "=============== clip: sampleTimeUs < startTime ===============" );
                    mediaExtractor.advance();
                    continue;
                } else if(sampleTimeUs > endTime){
                    Log.e("7777777777777777777", "=============== sampleTimeUs > endTime ===============" );
                    break;
                }
                Log.e("77777777777777777", "================ 111111111111111111 ================");

                info.size = mediaExtractor.readSampleData(buffer, 0);
                info.presentationTimeUs = sampleTimeUs;
                info.flags = mediaExtractor.getSampleFlags();

                byte[] content = new byte[buffer.remaining()];
                buffer.get(content);

                FileUtils.writeContent(content);
                ByteBuffer inputBuffer = mediaCodec.getInputBuffer(decodeInputIndex);
                inputBuffer.put(content);
                mediaCodec.queueInputBuffer(decodeInputIndex, 0, info.size, info.presentationTimeUs, info.flags);
                mediaExtractor.advance();
            }

            outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 100_000);
            while (outputBufferIndex >= 0){
                ByteBuffer decodeOutputBuffer = mediaCodec.getOutputBuffer(outputBufferIndex);
                writeChannel.write(decodeOutputBuffer);
                mediaCodec.releaseOutputBuffer(outputBufferIndex, false);
                outputBufferIndex = mediaCodec.dequeueOutputBuffer(info, 100_000);
            }
        }

        writeChannel.close();
        mediaExtractor.release();
        mediaCodec.stop();
        mediaCodec.release();

        File waveFile = new File(Environment.getExternalStorageDirectory(), "output.mp3");
        new PcmToWavUtil(44100,  AudioFormat.CHANNEL_IN_STEREO,
                2, AudioFormat.ENCODING_PCM_16BIT).pcmToWav(pcmFile.getAbsolutePath()
                , waveFile.getAbsolutePath());
        Log.e("77777777777777777", "================ 22222222222222222222222222 ================");
    }


}
